#include "leveltransitionstate.h"
#include "levelbeginstate.h"

void LevelTransitionState::ClientInit()
{
	m_work_manager = m_client->work_manager();
	m_guid = m_client->GetGUID();
}

void LevelTransitionState::ClientCleanup()
{
	if (m_shutdown_network_on_state_end)
	{
		m_client->Shutdown();
		delete m_client;
	}
}

void LevelTransitionState::DoClientWork()
{
	Job next_job;
	while (m_work_manager->GetJobToLocal(next_job))
	{
		unsigned char type_id;
		next_job.data->Read(type_id);
		switch (type_id)
		{
		case ID_DISCONNECTION_NOTIFICATION:
		case ID_CONNECTION_LOST:
			ClientProcessClosedConnection();
			break;

		case ID_REMOVE_CLIENT:
			ClientProcessRemoveClient(next_job);
			break;

		case ID_LEVELFILE:
			ClientProcessLevelFile(next_job);
			break;

		case ID_GOTO_LEVELBEGIN:
			ClientProcessGotoLevelBegin();
		};

		next_job.JobDone();
	}
}

void LevelTransitionState::ClientProcessClosedConnection()
{
	// We have been disconnected.
	// TODO: Do something that makes sense (i.e. state change, ...)
	m_shutdown_network_on_state_end = true;
	m_engine->set_end_game(true);
}

void LevelTransitionState::ClientProcessRemoveClient(Job remove_client_job)
{
	RakNet::RakString guid_string;
	RakNet::StringCompressor::Instance()->DecodeString(&guid_string, 64, remove_client_job.data);
	m_client_list.RemoveClient(std::string(guid_string.C_String()));
}

void LevelTransitionState::ClientProcessLevelFile(Job level_file_job)
{
	if(!m_level_loaded)
	{
		RakNet::RakString level_file_string;
		RakNet::StringCompressor::Instance()->DecodeString(&level_file_string, MAX_LEVELSIZE_IN_BYTE, level_file_job.data);

		LoadLevel(std::string(level_file_string.C_String()));
	}

	// Send ready signal.
	Job job(ID_CLIENT_READY);
	m_work_manager->JobToRemote(job);
}

void LevelTransitionState::ClientProcessGotoLevelBegin()
{
	m_shutdown_network_on_state_end = false;

	LevelBeginState* next_state = new LevelBeginState(m_engine);
	next_state->Init(m_is_server, m_server, m_client, m_client_list, m_level);
	m_engine->SetNextState(next_state);
}

void LevelTransitionState::ClientUpdate()
{
	DoClientWork();
}